#include <system.h>
#include <lib.h>

/*  Need to code these */
void *memcpy(void *dest, const void *src, size_t count)
{
	/* Add code here to copy 'count' bytes of date from src to
	*  'dest', finaly return 'dest' */

	/*  3/30/12 copied from bran's tutorial 
	* so void represents an unknown type and
	* size_t represents a count of bytes */

	const char *sp = (const char *)src;
	char *dp = (char *)dest;
	for (; count != 0; count--) *dp++ = *sp++;
	return dest;
}

void *memset(void *dest, char val, size_t count)
{
	/* Add code here to set 'count' bytes in 'dest' to 'val'.
	 * Again, return 'dest' */
	/* 3/30/2012 copied from bran's tutorial */

	char *temp = (char *)dest;
	for (; count != 0; count--) *temp++ = val;
	return dest;
}

unsigned short *memsetw(unsigned short *dest, unsigned short val, size_t 
count)
{
	/* Same as above, except, working with a 16-bit 'val'
	 * and dest pointer. Code can be an exact copy of the
	 * above, provided that your local variables if any,
	 * are unsined short */

	/* 3/30/2012 Stolen from bran's tutorial! */

	unsigned short *temp = (unsigned short *)dest;
	for (; count != 0; count--) *temp++ = val;
	return dest;
}

size_t strlen(const char *str)
{
	/* loops through character array 'str', returning how
	 * many characters it needs to check befor it finds a
	 * 0. Returns the length in bytes of a string */
	
	size_t retval;
	for(retval = 0; *str != '\0'; str++) retval++;
	return retval;
}

/* Used later for reading from the I/O ports to get data from
*  devices such as the keyboard.This is 'inline assembly' used
*  to actually do the work */
unsigned char inportb (unsigned short _port)
{
	unsigned char rv;
	__asm__ __volatile__ ("inb %1, %0" : "=a" (rv) : "dN" (_port));
	return rv;
}

/* Used this to write to I/O ports to send bytes to devices.
*  This will be used for changing the textmode cursor position.
*  Again, using inline assembly for the stuff that cannot be
*  done in C */
void outportb (unsigned short _port, unsigned char _data)
{
	__asm__ __volatile__ ("outb %1, %0" : : "dN" (_port), "a" (_data));
}


/* Dummy Enqueue functions at the request of Dr. Reese! */
BOOL Enqueue(int scanCode) asm("Enqueue");
BOOL Enqueue(int scanCode)
{
	return TRUE;
}

/* This is a simple main() function. All it does is sit in
*  an infinite loop. Basically, an 'idle' loop */
int main(void)
{
	/* commands here */
	Init8259();
	init_video();
	clearScreen();
	setTextColor(0x02, 0x00);
	puts("El-Kernel Version 0.1");
	puts("\n");
	setTextColor(0x03, 0x00);
	puts("Of course this is harmless...");
	puts("\n");
	puts("\n");
	setTextColor(0x02, 0x00);
	puts("Command: ");
	

	unsigned char scancode = "";
	unsigned char oldcode = "";

	while(1)
	{	
		oldcode = scancode;
		scancode = inportb(0x60);
		
		if (scancode & 0x80)
		{
			// check for shift, alt, and ctrl released
 		}
		else
		{
			putch(kbdus[scancode]);
			if (scancode)
			{
				int timer = 0;
				for(;timer<=20000000;timer++);
			}	
		}
	}
	
	//for (i = 0; i < 9999999; i++)
	//{
	//	puts(i);
	//}
	/* leave this loop in. Also an endless loop in
	*  'start.asm' if accidentally delete this next line */
	for (;;);
	return 0;
}
